// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

import { DataGrid, default as NodeGrid, GirdType} from "./nodeGrid";

const {ccclass, property} = cc._decorator;

@ccclass
export default class findPaht extends cc.Component {

    @property(cc.Node)
    nodeGridPrefab: cc.Node = null; //格子

    dataGrids: DataGrid[][] = []; //格子数据层面
    nodeGrids: NodeGrid[][] = []; //格子渲染层面

    startGrid: DataGrid = null; //开始点数据
    endGrid: DataGrid = null;   //结束点数据
   

    // LIFE-CYCLE CALLBACKS:

    onLoad () {}

    start () {
        this.generateMap();
    }

    //生成逻辑
    generateMap() {
        for(let i = 0; i < 10; i++){
            this.dataGrids[i] = [];
            this.nodeGrids[i] = [];
            for(let j = 0; j < 10; j++){
                //默认格子状态全部为正常状态
                //随机为墙的状态
                let rand = Math.random();
                let girdType: GirdType = GirdType.Normal; 
                if(rand < 0){
                    girdType = GirdType.Wall;
                }

                //初始化格子数据,加入对应数组
                let gridData = new DataGrid(girdType, i, j);
                this.dataGrids[i][j] = gridData;

                //初始化格子显示节点，加入到对应的数据
                let node = this.nodeGridPrefab;
                const value = node.height + 1;
                let nodeGrid = cc.instantiate(node).getComponent(NodeGrid);
                nodeGrid.node.parent = this.node;
                nodeGrid.node.position = cc.v3(value * (i - 5), value * (j - 5),0);
                nodeGrid.dataGrid = gridData;
                nodeGrid.findPaht = this;
                nodeGrid.updateGridColor();
                this.nodeGrids[i][j] = nodeGrid;
            }
        }
    }

    //确认开始和结束点逻辑
    onTouch(nodeGrid: NodeGrid){
        //点击对开始节点和结束节点的初始化
        if(!this.startGrid){
            this.startGrid = nodeGrid.dataGrid;
            this.startGrid.type = GirdType.Start;
            nodeGrid.updateGridColor(); //渲染更新一次
        }
        else if(!this.endGrid){
            this.endGrid = nodeGrid.dataGrid;
            this.endGrid.type = GirdType.End;
            nodeGrid.updateGridColor(); //渲染更新一次

            //调用寻路逻辑
            this.startFindPath();
        }
    }

     /**
     * 把开始节点加入到存储中，并标记好。
     * 查找可以走的下一步节点，按照条件距离最近的进行排序
     * 把下一步可走的节点当作当先寻路节点
     * 把走过的节点在标记一下
     */
    //开始寻路
    pathArray: DataGrid[] = []; //记录所有路径数据
    startFindPath() {
       if(this.find(this.startGrid)){
            for(let i = 0; i < this.pathArray.length; i++){
                let path = this.pathArray[i];
                path.type = GirdType.Road;
                this.scheduleOnce(() => {
                    this.nodeGrids[path.i][path.j].updateGridColor();
                }, i * 0.1);
                
            }
       }else{
            cc.log("不存在路径!!!!!")
       }
    }

    //递归查找
    find(grid: DataGrid){
        this.pathArray.push(grid);
        grid.inOpen = true;

        if(grid == this.endGrid){ //等于终点时候停止
            return true;
        }

        let roundGrids = this.getRoundGridData(grid);
        //cc.error("ERRR---->>>",roundGrids)
        for(let i = 0; i < roundGrids.length; i++){
            let nextGrid = roundGrids[i];
            if(this.find(nextGrid)){
                return true;
            }
        }

        this.pathArray.splice(this.pathArray.length -1,1);
        grid.inClose = true;
        return false;
    }

    getRoundGridData(grid: DataGrid): DataGrid[]{
        let arr: DataGrid[] = [];
        //四个方向
        this.addToRoundArray(arr, this.getGridData(grid.i + 1, grid.j)); //上
        this.addToRoundArray(arr, this.getGridData(grid.i - 1, grid.j)); //下
        this.addToRoundArray(arr, this.getGridData(grid.i, grid.j + 1)); //左
        this.addToRoundArray(arr, this.getGridData(grid.i, grid.j - 1)); //右
        //另外四个方向
        // this.addToRoundArray(arr, this.getGridData(grid.i + 1, grid.j + 1)); //右上
        // this.addToRoundArray(arr, this.getGridData(grid.i + 1, grid.j - 1)); //右下
        // this.addToRoundArray(arr, this.getGridData(grid.i - 1, grid.j + 1)); //左上
        // this.addToRoundArray(arr, this.getGridData(grid.i - 1, grid.j - 1)); //左下
        arr.sort(this.compareGrids.bind(this));
        return arr;
    }
    addToRoundArray(arr: DataGrid[], roundGrid: DataGrid){
        //判断不允许加入存储结构中的条件
        if(roundGrid){
            if(roundGrid.type == GirdType.Wall) { return;} //墙不允许加入
            if(roundGrid.inOpen) { return;}  //已经加入的
            if(roundGrid.inClose) { return;} //
            arr.push(roundGrid);
        }
    }

    getGridData(i: number, j: number) :DataGrid {
        //对于不存在的行列数据进行判断
        if(i < 0 || i >= 10 || j < 0 || j >= 10){ return null;}
        return this.dataGrids[i][j];
    }

    //排序比较
    compareGrids(grid0: DataGrid, grid1: DataGrid){
        let score0 = this.getScore(grid0, this.endGrid);
        let score1 = this.getScore(grid1, this.endGrid);
        if(score0 < score1){ return -1;}
        else if(score0 > score1){ return 1;}
        else{ return 0;}
    }
    getScore(grid: DataGrid, end: DataGrid): number{
        return Math.abs(grid.i - end.i) + Math.abs(grid.j - end.j);
    }
}  

